const CONFIG = require("../../config");
const wechatConfig = CONFIG.wechat;
const WXBizDataCrypt = require("../../utils/wechat_bizdata");
const Dayjs = require("dayjs");
const MYSQL = require("../../sql/mysql");
const sqlName = "wechat_access_token";

/**
 * 解密用户数据
 * @param {object} params 配置对象
 * @param {string} params.sessionKey sessionKey
 * @param {string} params.encryptedData encryptedData
 * @param {string} params.iv iv
 * @returns {Promise<{object}>}
 */
async function BizData(params = {}) {
  let { session_key, encryptedData, iv } = params;

  if (!session_key) {
    throw {
      code: 500,
      msg: "session_key 不能为空",
    };
  } else if (!encryptedData) {
    throw {
      code: 500,
      msg: "encryptedData 不能为空",
    };
  } else if (!iv) {
    throw {
      code: 500,
      msg: "iv 不能为空",
    };
  }

  let appid = wechatConfig.appid;
  let pc = new WXBizDataCrypt(appid, session_key);
  let data = pc.decryptData(encryptedData, iv);
  return data;
}

/**
 * 获取微信login code
 * @param {object} params 
 * @param {string} params.code wx.login 获得的code
 * @return {Promise<{code:number,msg:string,data:{openid:string,session_key:string}} | {code:number,msg:string}>}
 */
async function loginCode(params = {}) {
  let {code} = params 
  if (!code) {
    throw { code: 500, msg: "code不能为空" };
  }
  let appid = wechatConfig.appid;
  let secret = wechatConfig.secret;
  let url = "https://api.weixin.qq.com/sns/jscode2session";
  let WechatUserInfo = null;
  try {
    WechatUserInfo = await http.get(url, {
      appid,
      secret,
      js_code: code,
      grant_type: "authorization_code",
    });
  } catch (error) {
    throw {
      code: 500,
      msg: "获取失败,在请求微信服务器时发生错误 -1",
    };
  }
  if (WechatUserInfo && WechatUserInfo.openid && WechatUserInfo.session_key) {
    let { openid, session_key } = WechatUserInfo;
    return {
      code: 0,
      msg: "获取成功",
      data: {
        openid,
        session_key,
      },
    };
  } else {
    let { errcode, errmsg } = WechatUserInfo;
    throw {
      code: 500,
      msg: "获取失败,在请求微信服务器时发生错误 -2",
      errcode,
      errmsg,
    };
  }
}

/**
 * 微信获取用户手机号(新版本)
 * @param {object} params 配置对象
 * @param {string} [params.access_token] token
 * @param {string} params.loginCode code
 * @param {string} params.phoneCode code
 * @return {Promise<{code:number,msg:string,data:{openid:string,session_key:string}} | {code:number,msg:string}>}
 */
async function MobileCode(params = {}) {
  try {
    let { access_token, code } = params;
    if (!code) {
      throw {
        code: 502,
        msg: "code不能为空",
      };
    }
    // 请求服务器获取手机号 ==================================、
    let requestMobileInfoResult;
    let url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber";
    try {
      requestMobileInfoResult = await http.post(
        `${url}?access_token=${access_token}`,
        {
          code,
        }
      );
    } catch (error) {
      console.log(error);
      throw { code: 500, msg: "操作失败,在请求微信服务器时发生错误 -2" };
    }
    let errcode = requestMobileInfoResult.errcode;
    if (errcode == 40029) {
      throw { code: 500, msg: "获取失败,code 无效", code };
    } else if (errcode == -1) {
      throw {
        code: 500,
        msg: "获取失败,微信服务器系统繁忙，稍候再试",
        code,
      };
    } else if (errcode != 0) {
      throw { code: 500, msg: "获取失败,未知错误", code: phoneCode };
    }
    // 接口结束，返回数据  ==================================、
    return {
      code: 0,
      msg: "获取成功",
      data: requestMobileInfoResult.phone_info,
    };
  } catch (error) {
    console.log("获取微信手机号模块出错");
    console.log(error);
    throw { code: 500, msg: "获取微信手机号模块出错" };
  }
}

/**
 * 获取微信服务器操作access_token
 * @returns {Promise<object>} 返回结果
 */
async function getAccessToken() {
  let appid = wechatConfig.appid;
  let secret = wechatConfig.secret;
  // 当前时间
  let date_now = Dayjs(Date.now()).valueOf();
  // 获取access_token记录语句
  let sqlQuery = `SELECT * FROM ${sqlName} WHERE expires_date > ${date_now} and state = 1`;
  let get_access_token = [];
  try {
    get_access_token = await MYSQL.queryPromise(sqlQuery);
  } catch (err) {
    throw {
      code: 500,
      msg: "操作失败,在获取access_token记录时失败",
    };
  }
  if (get_access_token.length) {
    let access_token_data = get_access_token[0];
    return {
      code: 0,
      msg: "获取成功",
      access_token: access_token_data.access_token,
    };
  } else {
    let getAccessTokenResult = null;
    try {
      getAccessTokenResult = await http.get(
        `https://api.weixin.qq.com/cgi-bin/token`,
        {
          grant_type: "client_credential",
          appid,
          secret,
        }
      );
    } catch (error) {
      let errcode = getAccessTokenResult.errcode;
      if (errcode) {
        throw {
          code: 500,
          msg: "操作失败,在请求access_token时发生错误失败",
        };
      } else {
        let { access_token, expires_in } = getAccessTokenResult;
        let addQuery = `INSERT INTO ${sqlName} SET 
          access_token = '${access_token}',
          create_date = '${create_date}',
          expires_date = '${date_now + expires_in * 1000}',
          state = 1
        `;
        let insertResule = null;
        try {
          insertResule = await MYSQL.query(addQuery);
        } catch (error) {
          throw {
            code: 500,
            msg: "操作失败,在记录access_token时发生错误",
          };
        }
        return {
          code: 0,
          msg: "获取成功",
          access_token: insertResule.access_token,
        };
      }
    }
  }
}

/**
 * 微信登录
 */
async function wechatLogin(params = {}) {
  return {
    code: 0,
    msg: "登录成功",
  };
}

module.exports = {
  loginCode,
  MobileCode,
  BizData,
  getAccessToken,
  wechatLogin,
};
